﻿using Prism.Commands;
using Prism.Regions;
using Quartz;
using Quartz.Impl.Matchers;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ZYing.QPanel.ViewModels
{
    public class HistoryViewModel : NavigationViewModelBase
    {
        public ObservableCollection<HistoryItemViewModel> Items { get; } = new ObservableCollection<HistoryItemViewModel>();
        private readonly IScheduler _scheduler;
        private readonly IRegionManager _regionManager;
        public HistoryViewModel(IScheduler scheduler, IRegionManager regionManager)
        {
            _scheduler = scheduler ?? throw new ArgumentNullException(nameof(scheduler));
            _regionManager = regionManager ?? throw new ArgumentNullException(nameof(regionManager));
            ReloadCommand = new DelegateCommand(DoReload);
            CloseDrawerCommand = new DelegateCommand(CloseDrawer);
            Run(this.CancellationTokenSource.Token);
        }
        public DelegateCommand ReloadCommand { get; }
        public ObservableCollection<string> JobGroups { get; } = new ObservableCollection<string>();
        public ObservableCollection<string> TriggerGroups { get; } = new ObservableCollection<string>();
        private string _jobGroup;

        public string JobGroup
        {
            get { return _jobGroup; }
            set { if (SetProperty(ref _jobGroup, value)) this.DoReload(); }
        }
        private string _triggerGroup;

        public string TriggerGroup
        {
            get { return _triggerGroup; }
            set { if (SetProperty(ref _triggerGroup, value)) this.DoReload(); }
        }
        private string _keyword;

        public string Keyword
        {
            get { return _keyword; }
            set { if (SetProperty(ref _keyword, value)) this.DoReload(); }
        }

        private JobState? _jobState;

        public JobState? JobState
        {
            get { return _jobState; }
            set { if (SetProperty(ref _jobState, value)) this.DoReload(); }
        }
        public List<JobState> JobStates { get; } = new List<JobState> {
            QPanel.JobState.Running,
            QPanel.JobState.Complated,
            QPanel.JobState.Fail
        };
        private async void Run(CancellationToken cancellationToken)
        {
            while (true)
            {
                if (cancellationToken.IsCancellationRequested) break;
                if (this.IsActive)
                {
                    try
                    {
                        await Reload();
                    }
                    catch (Exception e)
                    {
                        Trace.WriteLine(e);
                    }
                }
                await Task.Delay(1000);
            }
        }
        private readonly FilterInput _filterInput = new FilterInput { Limit = 50 };
        private async Task Reload()
        {

            var jobGroups = await _scheduler.GetJobGroupNames();
            foreach (var g in jobGroups)
            {
                if (JobGroups.Contains(g)) continue;
                JobGroups.Add(g);
            }

            var triggerGroups = await _scheduler.GetTriggerGroupNames();
            foreach (var g in triggerGroups)
            {
                if (TriggerGroups.Contains(g)) continue;
                TriggerGroups.Add(g);
            }

            if (!_scheduler.Context.TryGetExecutionHistoryStore(out var store)) return;
            if (!string.IsNullOrWhiteSpace(this.JobGroup))
            {
                _filterInput.JobMatcher = GroupMatcher<JobKey>.GroupEquals(this.JobGroup);
            }
            else
            {
                _filterInput.JobMatcher = null;
            }
            if (!string.IsNullOrWhiteSpace(this.TriggerGroup))
            {
                _filterInput.TriggerMatcher = GroupMatcher<TriggerKey>.GroupEquals(this.TriggerGroup);
            }
            else
            {
                _filterInput.TriggerMatcher = null;
            }
            _filterInput.Keyword = this.Keyword;
            _filterInput.JobState = this.JobState;
            var items = await store.FilterLast(_filterInput);
            var dic = Items.ToDictionary(i => i.Id, i => i);
            foreach (var e in items.Reverse())
            {
                if (dic.TryGetValue(e.FireInstanceId, out var vm))
                {
                    vm.Read(e, store);
                    dic.Remove(e.FireInstanceId);
                }
                else
                {
                    vm = new HistoryItemViewModel(e);
                    vm.Read(e, store);
                    this.Items.Insert(0, vm);
                }
            }
            if (dic.Count > 0)
            {
                foreach (var item in dic.Values)
                {
                    this.Items.Remove(item);
                }
            }
        }
        private async void DoReload()
        {
            await this.Reload();
        }
        private HistoryItemViewModel _current;

        public HistoryItemViewModel Current
        {
            get { return _current; }
            set
            {
                if (SetProperty(ref _current, value))
                {
                    if (_current != null)
                    {
                        this.IsDrawerOpen = true;
                        var p = new NavigationParameters();
                        p.Add("id", _current.Id);
                        p.Add("job", _current.Job);
                        _regionManager.RequestNavigate(Constants.RegionConstants.HistoryDetail, typeof(Views.HistoryDetail).FullName, p);
                    }
                }
            }
        }


        private bool _isDrawerOpen;

        public bool IsDrawerOpen
        {
            get { return _isDrawerOpen; }
            set { SetProperty(ref _isDrawerOpen, value); }
        }
        public void CloseDrawer()
        {
            IsDrawerOpen = false;
            _regionManager.Regions[Constants.RegionConstants.HistoryDetail].RemoveAll();
            Current = null;
        }
        public DelegateCommand CloseDrawerCommand { get; }
    }
}
